package chapter5.homework.oldSeries.Q3updateJPG;

import java.io.*;
import java.net.Socket;
import java.security.MessageDigest;

/**
 * @Project ：learn_java
 * @File ：Client.java
 * @IDE ：IntelliJ IDEA
 * @Author ：自由如风间
 * @Date ：2025/3/17 17:00
 * @Description ：
 * 向服务器分别上传jpg和png两种格式的图片，
 * 验证成功还会向服务器发送文件md5以供服务器校验文件完整性，
 * 本地实现了进度条功能，
 * 可以接收服务器返回的是否可行和具体错误信息和是否成功的信息
 */

public class Client {

    /**
     * 计算文件md5值
     * @param file 传入的文件
     * @return 文件md值
     * @throws Exception
     */
    private static String calculateFileHash(File file) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                md.update(buffer, 0, bytesRead);
            }
            byte[] hashBytes = md.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : hashBytes) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        }
    }

    public static void main(String[] args) throws IOException {
        String localhost = "127.0.0.1";
        int defaultPort = 10000;
        // 创建socket对象并连接服务端
        Socket socket = new Socket(localhost, defaultPort);

        // 构建IO
        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();

        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));

        File pngFile = new File("G:\\codes\\learn_java\\images\\girlAndCat.png");
        File jpgFile = new File("G:\\codes\\learn_java\\images\\p.jpg");

        File[] files = new File[2];
        files[0] = pngFile;
        files[1] = jpgFile;

        try {
            // 因为是学习目的，这里直接用两次循环写死
            for (int i = 0; i < 2; i++) {
                DataInputStream dis = new DataInputStream(is);
                DataOutputStream dos = new DataOutputStream(os);

                File f = files[i];

                /*
                检查文件是否存在
                */
                if (!f.exists()) {
                    System.out.println(files[i] + " 不存在，请检查路径。");
                    continue;
                }

                long fileSize = f.length();
                String fileName = f.getName();

                // 发送文件大小和文件名
                dos.writeLong(fileSize);
                dos.writeUTF(fileName);

                /*
                读取服务器文件验证返回结果的编码
                */
                int feedback = dis.readInt();
                if (feedback == 1) {
                    System.out.println("不支持上传JPG之外格式的图片呢。￣へ￣");
                    continue;
                } else if (feedback == 2) {
                    System.out.println("只能上传2MB以内的图片哟。ψ(｀∇´)ψ");
                    continue;
                }

                /*
                发送文件内容
                */
                byte[] buffer = new byte[4096];
                int bytesRead;
                // 进度条初始化
                long totalSent = 0;
                System.out.println("开始上传: " + fileName);

                FileInputStream fis = new FileInputStream(f.getAbsolutePath());
                while ((bytesRead = fis.read(buffer)) != -1) {
                    os.write(buffer, 0, bytesRead);
                    totalSent += bytesRead;
                    // 进度计算
                    double progress = (double) totalSent / fileSize * 100;
                    // 很简单的数值进度打印
                    // System.out.printf("上传进度: %.2f%%\r", progress);
                    // 稍带图形的条状进度打印
                    String uploadBar = "[";
                    uploadBar += "=".repeat((int)progress / 10) + ">\t]";
                    System.out.printf("上传进度：%s%.2f%%\r", uploadBar, progress);
                }

                System.out.println();

                fis.close();

                /*
                发送md5值
                */
                String fileHash = calculateFileHash(f);
                dos.writeUTF(fileHash);

                /*
                打印上传是否成功信息
                */
                boolean uploadSucceed = dis.readBoolean();
                System.out.println("文件上传" + (uploadSucceed ? "成功" : "失败，请稍后重试"));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
